package org.robot.scm.platform.wxrobot.processor;

import com.fasterxml.jackson.core.type.TypeReference;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import java.io.File;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.ThreadLocalRandom;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.robot.scm.infra.LocalCacheHelper;
import org.robot.scm.infra.RedisCacheHelper;
import org.robot.scm.platform.wxrobot.AbstractRobotProcessor;
import org.robot.scm.pojos.TargetNotify;
import org.robot.scm.pojos.config.BaseConfig;
import org.robot.scm.pojos.config.base.BasePlatform;
import org.robot.scm.pojos.enums.PlatformEnum;
import org.robot.scm.pojos.platform.MessageBaseNotify;
import org.robot.scm.retry.SimpleRetryable;
import org.robot.scm.utils.JsonHelper;
import org.robot.scm.utils.StreamUtils;

/**
 * 吃什么投票
 *
 * @Author : Awn create on 2024/4/22 15:52
 */
@Slf4j
public class EatVoteRobotProcessor extends AbstractRobotProcessor {

    private static final String TAG = EatVoteRobotProcessor.class.getSimpleName();

    private static final String WHAT_TAG = EatWhatRobotProcessor.class.getSimpleName();

    private final static Map<Integer, String> charMap = new HashMap<>() {
        {
            put(0, "A");
            put(1, "B");
            put(2, "C");
            put(3, "D");
        }
    };

    private final static Map<Integer, Integer> voteMap = new HashMap<>() {
        {
            put(0, 0);
            put(1, 0);
            put(2, 0);
            put(3, 0);
        }
    };

    private static void restoreVote() {
        voteMap.put(0, 0);
        voteMap.put(1, 0);
        voteMap.put(2, 0);
        voteMap.put(3, 0);
    }

    private static Integer finalVote() {
        return StreamUtils.sumToInt(voteMap.values(), Integer::intValue);
    }

    private static Integer voteIndex() {
        int idx = 0;
        int cnt = 0;
        for (Map.Entry<Integer, Integer> entry : voteMap.entrySet()) {
            if (entry.getValue() > cnt) {
                cnt = entry.getValue();
                idx = entry.getKey();
            }
        }
        return idx;
    }

    @Override
    public List<String> getKeywords(BaseConfig config) {
        return config.get().getPlatform(PlatformEnum.EATVOTE).getKeywords();
    }

    @Override
    protected List<TargetNotify> process(BaseConfig config, String sendTo, String msg) {
        return new SimpleRetryable(3, 2000).retry(() -> this.doProcess(config, sendTo, msg), Objects::nonNull);
    }

    private List<TargetNotify> doProcess(BaseConfig config, String sendTo, String msg) {
        String EATVOTE = RedisCacheHelper.get(WHAT_TAG);
        if (StringUtils.isNotBlank(EATVOTE)) {
            restoreVote();
            MessageBaseNotify whatBean = MessageBaseNotify.builder().message("🍚投票结果 👉 " + EATVOTE).build();
            List<String> filter = StreamUtils.filter(config.get().getRobots(PlatformEnum.EATWHAT), e -> StringUtils.equals(e, sendTo));
            return StreamUtils.convertAndDistinct(filter, e -> whatBean.robotToNotifyBean(e, config));
        }

        List<String> voteList = JsonHelper.toList(RedisCacheHelper.get(TAG), new TypeReference<>() {
        });
        if (CollectionUtils.isNotEmpty(voteList)) {
            // 投票结果大于2人
            if (finalVote() > 2) {
                RedisCacheHelper.put(WHAT_TAG, voteList.get(voteIndex()), 10 * 3600);
                String builder = "🍚投票结果 👉 " + voteList.get(voteIndex());
                MessageBaseNotify whatBean = MessageBaseNotify.builder().message(builder).build();
                List<String> filter = StreamUtils.filter(config.get().getRobots(PlatformEnum.EATWHAT), e -> StringUtils.equals(e, sendTo));
                return StreamUtils.convertAndDistinct(filter, e -> whatBean.robotToNotifyBean(e, config));
            }

            if (StringUtils.equalsAnyIgnoreCase(msg, "A")) {
                voteMap.put(0, voteMap.get(0) + 1);
            }
            if (StringUtils.equalsAnyIgnoreCase(msg, "B")) {
                voteMap.put(1, voteMap.get(1) + 1);
            }
            if (StringUtils.equalsAnyIgnoreCase(msg, "C")) {
                voteMap.put(2, voteMap.get(2) + 1);
            }
            if (StringUtils.equalsAnyIgnoreCase(msg, "D")) {
                voteMap.put(3, voteMap.get(3) + 1);
            }
            return Lists.newArrayList();
        }

        // 重置投票结果
        restoreVote();

        BasePlatform currentPlatform = config.get().getPlatform(PlatformEnum.EATWHAT);
        List<String> urlTextList = JsonHelper.toList(LocalCacheHelper.get(TAG));
        if (CollectionUtils.isEmpty(urlTextList)) {
            urlTextList.addAll(this.loadAndCache(currentPlatform.getNoticeSrc()));
        }

        Set<String> whatSets = Sets.newHashSet();
        while (whatSets.size() < 4) {
            this.shuffle(urlTextList);
            whatSets.add(urlTextList.get(0));
        }

        List<String> whatList = Lists.newArrayList(whatSets);
        StringBuilder builder = new StringBuilder("🥬精选四家美食\n");
        for (int i = 0; i < whatList.size(); i++) {
            builder.append("【").append(charMap.get(i)).append("】").append(whatList.get(i)).append("\n");
        }
        builder.append("👉吃货请投票👈");

        // 8:00 - 18:00 10个小时缓存
        RedisCacheHelper.put(TAG, JsonHelper.toJSONString(whatList), 10 * 3600);
        MessageBaseNotify whatBean = MessageBaseNotify.builder().message(builder.toString()).build();
        List<String> filter = StreamUtils.filter(config.get().getRobots(PlatformEnum.EATWHAT), e -> StringUtils.equals(e, sendTo));
        return StreamUtils.convertAndDistinct(filter, e -> whatBean.robotToNotifyBean(e, config));
    }

    @SneakyThrows
    private List<String> loadAndCache(String noticeSrc) {
        String jsonConfig = FileUtils.readFileToString(new File(noticeSrc), StandardCharsets.UTF_8.name());
        List<String> what = JsonHelper.toList(jsonConfig);
        LocalCacheHelper.put(TAG, JsonHelper.toJSONString(what));
        return what;
    }

    /**
     * faster than Collections.shuffle()
     */
    private void shuffle(List<String> list) {
        Random random = ThreadLocalRandom.current();
        for (int i = list.size() - 1; i > 0; i--) {
            int j = random.nextInt(i + 1);
            list.set(i, list.set(j, list.get(i)));
        }
    }
}
